package com.rem.chat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.rem.chat.common.constants.Constants;
import com.rem.chat.common.errcode.ServiceErrorCodeConstants;
import com.rem.chat.common.exception.ServiceException;
import com.rem.chat.common.utils.BeanTransUtil;
import com.rem.chat.common.utils.RedisComponent;
import com.rem.chat.common.utils.StringUtil;
import com.rem.chat.mapper.*;
import com.rem.chat.pojo.dataobject.*;
import com.rem.chat.pojo.request.ApplyAddRequest;
import com.rem.chat.pojo.request.ApplyDealWithRequest;
import com.rem.chat.pojo.request.PageRequest;
import com.rem.chat.pojo.request.ContactSearchRequest;
import com.rem.chat.pojo.response.*;
import com.rem.chat.service.ContactService;
import com.rem.chat.service.dto.AddContactDTO;
import com.rem.chat.service.dto.ContactApplyDTO;
import com.rem.chat.service.dto.MessageSendDTO;
import com.rem.chat.service.dto.UserLoginDTO;
import com.rem.chat.service.enums.*;
import com.rem.chat.websocket.ChannelContextUtil;
import com.rem.chat.websocket.MessageHandler;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author: Themberfue
 * @date: 2025/6/6 20:36
 * @description:
 */
@Service
public class ContactServiceImpl implements ContactService {

    @Resource
    UserInfoMapper userInfoMapper;

    @Resource
    GroupInfoMapper groupInfoMapper;

    @Resource
    UserContactMapper userContactMapper;

    @Resource
    UserContactApplyMapper userContactApplyMapper;

    @Resource
    ChatSessionMapper chatSessionMapper;

    @Resource
    ChatSessionUserMapper chatSessionUserMapper;

    @Resource
    ChatMessageMapper chatMessageMapper;

    @Resource
    RedisComponent redisComponent;

    @Resource
    ChannelContextUtil channelContextUtil;

    @Resource
    MessageHandler messageHandler;

    @Override
    public List<SearchContactResponse> searchContact(ContactSearchRequest request) {
        String userId = request.getUserId(), contactId = request.getContactId();
        // Step 1. 假设搜索的是用户，查询该用户与被搜索用户的关系
        QueryWrapper<UserContactDO> queryUserWrapper = new QueryWrapper<>();
        queryUserWrapper.lambda()
                .eq(UserContactDO::getUserId, userId)
                .eq(UserContactDO::getContactId, UserContactTypeEnum.USER.getPrefix() + contactId);
        UserContactDO userContactDOByUser = userContactMapper.selectOne(queryUserWrapper);

        // Step 2. 搜索用户
        UserInfoDO userInfoDO = userInfoMapper.selectById(UserContactTypeEnum.USER.getPrefix() + contactId);
        SearchContactResponse userContact = BeanTransUtil.transToSearchContactResponse(userInfoDO, userId,
                null == userContactDOByUser ? null : userContactDOByUser.getStatus());

        // Step 3. 假设搜索的是群组，查询该用户与群组的关系
        QueryWrapper<UserContactDO> queryGroupWrapper = new QueryWrapper<>();
        queryGroupWrapper.lambda()
                .eq(UserContactDO::getUserId, userId)
                .eq(UserContactDO::getContactId, UserContactTypeEnum.GROUP.getPrefix() + contactId);
        UserContactDO userContactDOByGroup = userContactMapper.selectOne(queryGroupWrapper);

        // Step 4. 搜索群组
        GroupInfoDO groupInfoDO = groupInfoMapper.selectById(UserContactTypeEnum.GROUP.getPrefix() + contactId);
        // Step 5. 判断群聊状态（正常、解散）
        SearchContactResponse groupContact = null;
        if (null != groupInfoDO && groupInfoDO.getStatus()
                .equals(GroupStatusEnum.NORMAL.getStatus())) {
            groupContact = BeanTransUtil.transToSearchContactResponse(groupInfoDO,
                    null == userContactDOByGroup ? null : userContactDOByGroup.getStatus());
        }

        List<SearchContactResponse> contactList = new ArrayList<>();
        if (null != userContact) contactList.add(userContact);
        if (null != groupContact) contactList.add(groupContact);
        return contactList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean applyAdd(UserLoginDTO user, ApplyAddRequest request) {
        // Step 1. 获得联系人类型
        UserContactTypeEnum typeEnum = UserContactTypeEnum.getByPrefix(request.getContactId());
        if (null == typeEnum) {
            throw new ServiceException(ServiceErrorCodeConstants.CONTACT_TYPE_WRONG);
        }

        // Step 2. 处理默认申请信息
        String applyInfo = request.getApplyInfo();
        if (!StringUtils.hasLength(applyInfo)) {
            applyInfo = String.format(Constants.APPLY_INFO_TEMPLATE, user.getNickName());
        }

        // Step 3. 查询申请人和联系人的关系
        QueryWrapper<UserContactDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                    .eq(UserContactDO::getUserId, user.getUserId())
                    .eq(UserContactDO::getContactId, request.getContactId());
        UserContactDO userContactDO = userContactMapper.selectOne(queryWrapper);
        // ? 如果申请人被联系人拉黑，则不能申请
        if (null != userContactDO &&
                ArrayUtils.contains(new Integer[]{UserContactStatusEnum.BLACKLIST.getStatus(),
                                                UserContactStatusEnum.BLACKLIST_BE_FIRST.getStatus()},
                        userContactDO.getStatus())) {
            return false;
        }
        // ? 如果申请人已经和联系人是好友，则不能申请
        if (null != userContactDO && userContactDO.getStatus()
                .equals(UserContactStatusEnum.FRIEND.getStatus())) {
            return false;
        }

        Integer joinType;
        String receivedId;
        // Step 4. 根据联系人类型进行不同的处理
        if (typeEnum.equals(UserContactTypeEnum.USER)) { // ? 联系人为用户
            UserInfoDO userInfoDO = userInfoMapper.selectById(request.getContactId());
            if (null == userInfoDO) {
                throw new ServiceException(ServiceErrorCodeConstants.USER_IS_NOT_EXISTS);
            }
            receivedId = userInfoDO.getUserId();
            joinType = userInfoDO.getJoinType();
        } else { // ? 联系人为群组
            GroupInfoDO groupInfoDO = groupInfoMapper.selectById(request.getContactId());
            if (null == groupInfoDO) {
                throw new ServiceException(ServiceErrorCodeConstants.GROUP_IS_NOT_EXISTS);
            }
            // Step 4.1 判断群组成员是否已满
            if (isGroupMaxMembers(request.getContactId())) {
                throw new ServiceException(ServiceErrorCodeConstants.GROUP_MEMBERS_IS_FULL);
            }
            receivedId = groupInfoDO.getGroupOwnerId();
            joinType = groupInfoDO.getJoinType();
        }

        //  Step 5. 判断联系人添加类型
        if (joinType.equals(JoinTypeEnum.JOIN.getType())) { // ? 直接添加
            // Step 5.1 添加联系人
            AddContactDTO addContactDTO = AddContactDTO.builder()
                            .applyUserId(user.getUserId())
                            .contactId(request.getContactId())
                            .contactType(typeEnum.getType())
                            .applyInfo(applyInfo)
                            .build();
            addContact(addContactDTO);
            return true;
        }

        // ? 需要验证
        QueryWrapper<UserContactApplyDO> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda()
                .eq(UserContactApplyDO::getApplyUserId, user.getUserId())
                .eq(UserContactApplyDO::getContactId, request.getContactId())
                .eq(UserContactApplyDO::getReceiveUserId, receivedId);
        UserContactApplyDO userContactApplyDO = userContactApplyMapper.selectOne(queryWrapper1);

        // Step 6. 校验申请人是否已经申请过
        if (null == userContactApplyDO) { // ? 从未申请
            UserContactApplyDO userContactApply = UserContactApplyDO.builder()
                    .applyUserId(user.getUserId())
                    .applyInfo(applyInfo)
                    .contactId(request.getContactId())
                    .contactType(typeEnum.getType())
                    .receiveUserId(receivedId)
                    .lastApplyTime(System.currentTimeMillis())
                    .status(UserContactApplyStatusEnum.INIT.getStatus())
                    .build();
            // Step 6.1 添加记录到数据库
            userContactApplyMapper.insert(userContactApply);
        } else { // ? （被删了或被拒绝后重新添加）
            // Step 6.2 更新记录到数据库
            userContactApplyDO.setApplyInfo(applyInfo);
            userContactApplyDO.setLastApplyTime(System.currentTimeMillis());
            userContactApplyDO.setStatus(UserContactApplyStatusEnum.INIT.getStatus());
            userContactApplyMapper.updateById(userContactApplyDO);
        }

        if (null == userContactApplyDO ||
                !userContactApplyDO.getStatus().equals(UserContactApplyStatusEnum.INIT.getStatus())) {
            // Step 7. 发送 WS 消息
            MessageSendDTO<Object> messageSendDTO = MessageSendDTO.builder()
                    .messageType(MessageTypeEnum.CONTACT_APPLY.getType())
                    .messageContent(applyInfo)
                    .contactId(receivedId)
                    .build();
            messageHandler.sendMessage(messageSendDTO);
        }
        return true;
    }

    @Override
    public LoadAllApplyResponse loadApply(String userId, PageRequest param) {
        // Step 1. 校验参数
        if (null == param) {
            param = new PageRequest();
        }

        // Step 2. 查询该用户发出和接受的申请总数
        QueryWrapper<UserContactApplyDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(UserContactApplyDO::getApplyUserId, userId)
                .or()
                .eq(UserContactApplyDO::getReceiveUserId, userId);
        Long total = userContactApplyMapper.selectCount(queryWrapper);

        // Step 3. 进行分页查询
        Page<UserContactApplyDO> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        Page<ContactApplyDTO> contactApplyDTOPage = userContactApplyMapper.selectUserContactApplies(page, userId);
        List<LoadAllApplyResponse.ContactApplyInfo> contactApplyInfoList = contactApplyDTOPage.getRecords().stream()
                .map(BeanTransUtil::transToContactApplyInfo)
                .toList();

        return new LoadAllApplyResponse(total, contactApplyInfoList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean dealWithApply(String userId, ApplyDealWithRequest param) {
        UserContactApplyStatusEnum statusEnum = UserContactApplyStatusEnum.getByStatus(param.getStatus());
        // Step 1. 校验状态是否“合理”
        if (null == statusEnum || statusEnum.equals(UserContactApplyStatusEnum.INIT)) {
            throw new ServiceException(ServiceErrorCodeConstants.CONTACT_APPLY_TYPE_WRONG);
        }

        // Step 2. 校验是否为用户本人处理自己的申请消息
        UserContactApplyDO userContactApplyDO = userContactApplyMapper.selectById(param.getApplyId());
        if (null == userContactApplyDO ||
                !userId.equals(userContactApplyDO.getReceiveUserId()) ||
                userId.equals(userContactApplyDO.getApplyUserId())) {
            throw new ServiceException(ServiceErrorCodeConstants.NOT_USER_OPERATE);
        }

        UserContactApplyDO updateContactApply = UserContactApplyDO.builder()
                .applyId(param.getApplyId())
                .status(param.getStatus())
                .lastApplyTime(System.currentTimeMillis())
                .build();

        QueryWrapper<UserContactApplyDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(UserContactApplyDO::getApplyId, param.getApplyId())
                // ! 为了防止出现从同意状态又更新为其他状态（只能从未处理状态更新到其他状态）
                .eq(UserContactApplyDO::getStatus, UserContactApplyStatusEnum.INIT.getStatus());
        int updateRes = userContactApplyMapper.update(updateContactApply, queryWrapper);
        if (0 == updateRes) {
            throw new ServiceException(ServiceErrorCodeConstants.STATUS_UPDATE_WRONG);
        }

        // Step 3.1 同意添加
        if (UserContactApplyStatusEnum.PASS.equals(statusEnum)) {
            // Step 3.1.1 添加联系人
            AddContactDTO addContactDTO = AddContactDTO.builder()
                            .applyUserId(userContactApplyDO.getApplyUserId())
                            .contactId(userContactApplyDO.getContactId())
                            .contactType(userContactApplyDO.getContactType())
                            .applyInfo(userContactApplyDO.getApplyInfo())
                            .build();
            addContact(addContactDTO);
            return true;
        }

        // Step 3.2 拒绝添加
        if (UserContactApplyStatusEnum.REJECT.equals(statusEnum)) {
            // ? 已经更新，无需做其他处理
            return true;
        }

        // Step 3.3 拉黑
        if (UserContactApplyStatusEnum.BLACKLIST.equals(statusEnum)) {
            List<UserContactDO> userContactDOList = new ArrayList<>();
            // Step 3.3.1 将接收者对申请人的关系设置为"拉黑"
            UserContactDO userContactDO = UserContactDO.builder()
                    .userId(userContactApplyDO.getContactId())
                    .contactId(userContactApplyDO.getApplyUserId())
                    .contactType(userContactApplyDO.getContactType())
                    .status(UserContactStatusEnum.BLACKLIST.getStatus())
                    .build();
            userContactDOList.add(userContactDO);

            // Step 3.3.2 将申请人对接收者的关系设置为"首次被拉黑"
            userContactDO = UserContactDO.builder()
                    .userId(userContactApplyDO.getApplyUserId())
                    .contactId(userContactApplyDO.getContactId())
                    .contactType(userContactApplyDO.getContactType())
                    .status(UserContactStatusEnum.BLACKLIST_BE_FIRST.getStatus())
                    .build();
            userContactDOList.add(userContactDO);

            // Step 3.3.3 插入或更新关系状态
            insertOrUpdate(userContactDOList);

            return true;
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addContact(AddContactDTO addContactDTO) {
        // Step 1. 判断群组是否已满
        if (UserContactTypeEnum.GROUP.getType()
                .equals(addContactDTO.getContactType()) && isGroupMaxMembers(addContactDTO.getContactId())) {
            throw new ServiceException(ServiceErrorCodeConstants.GROUP_MEMBERS_IS_FULL);
        }

        List<UserContactDO> userContactDOList = new ArrayList<>();

        // Step 2. 将双方互相添加为好友
        UserContactDO userContactDO = UserContactDO.builder()
                .userId(addContactDTO.getApplyUserId())
                .contactId(addContactDTO.getContactId())
                .contactType(addContactDTO.getContactType())
                .status(UserContactStatusEnum.FRIEND.getStatus())
                .build();
        userContactDOList.add(userContactDO);
        // Step 3. 联系人类型为用户时，才需要互相添加，否则单向添加即可
        if (UserContactTypeEnum.USER.getType()
                .equals(addContactDTO.getContactType())) {
            userContactDO = UserContactDO.builder()
                    .userId(addContactDTO.getContactId())
                    .contactId(addContactDTO.getApplyUserId())
                    .contactType(addContactDTO.getContactType())
                    .status(UserContactStatusEnum.FRIEND.getStatus())
                    .build();
            userContactDOList.add(userContactDO);
        }

        // Step 4. 插入或更新关系状态
        insertOrUpdate(userContactDOList);

        String applyUserId = addContactDTO.getApplyUserId();
        String contactId = addContactDTO.getContactId();

        // Step 5. 将对方存入到缓存中
        redisComponent.saveUserContact(applyUserId, contactId);
        if (addContactDTO.getContactType()
                .equals(UserContactTypeEnum.USER.getType())) {
            redisComponent.saveUserContact(contactId, applyUserId);
        }

        // Step 6. 创建会话
        String sessionId;
        if (addContactDTO.getContactType()
                .equals(UserContactTypeEnum.USER.getType())) {
            sessionId = StringUtil.getSessionId(new String[]{applyUserId, contactId});
        } else {
            sessionId = StringUtil.getSessionId(new String[]{contactId});
        }

        List<ChatSessionUserDO> chatSessionUserDOList = new ArrayList<>();
        if (addContactDTO.getContactType()
                .equals(UserContactTypeEnum.USER.getType())) {
            // Step 6.1 创建聊天会话
            ChatSessionDO chatSessionDO = ChatSessionDO.builder()
                    .sessionId(sessionId)
                    .lastMessage(addContactDTO.getApplyInfo())
                    .lastReceiveTime(System.currentTimeMillis())
                    .build();
            chatSessionMapper.insertOrUpdate(chatSessionDO);

            // Step 6.2 创建申请用户聊天会话
            UserInfoDO userInfo = userInfoMapper.selectById(applyUserId);
            ChatSessionUserDO userChatSession = ChatSessionUserDO.builder()
                    .sessionId(sessionId)
                    .userId(applyUserId)
                    .contactId(contactId)
                    .contactName(userInfo.getNickName())
                    .build();
            chatSessionUserDOList.add(userChatSession);

            // Step 6.3 创建接收用户聊天会话
            UserInfoDO contactInfo = userInfoMapper.selectById(contactId);
            ChatSessionUserDO contactChatSession = ChatSessionUserDO.builder()
                    .sessionId(sessionId)
                    .userId(contactId)
                    .contactId(applyUserId)
                    .contactName(contactInfo.getNickName())
                    .build();
            chatSessionUserDOList.add(contactChatSession);
            insertOrUpdate(chatSessionUserDOList, 0);

            // Step 6.4 创建消息信息
            ChatMessageDO chatMessageDO = ChatMessageDO.builder()
                    .sessionId(sessionId)
                    .messageContent(addContactDTO.getApplyInfo())
                    .messageType(MessageTypeEnum.ADD_FRIEND.getType())
                    .sendUserId(applyUserId)
                    .sendUserNickName(userInfo.getNickName())
                    .contactId(contactId)
                    .contactType(UserContactTypeEnum.USER.getType())
                    .build();
            chatMessageMapper.insert(chatMessageDO);

            MessageSendDTO<Object> messageSendDTO = BeanUtil.copyProperties(chatMessageDO, MessageSendDTO.class);
            // Step 7.1 发送给接受好友申请的人
            messageHandler.sendMessage(messageSendDTO);

            // Step 7.2 发送给申请人，接受人就是发送人，联系人就是申请人
            messageSendDTO.setMessageType(MessageTypeEnum.ADD_FRIEND_SELF.getType());
            messageSendDTO.setContactId(applyUserId);
            messageSendDTO.setExtendData(contactInfo);
            messageHandler.sendMessage(messageSendDTO);
        } else { // ? 加入群组
            // Step 6.1 创建聊天会话
            GroupInfoDO groupInfoDO = groupInfoMapper.selectById(contactId);
            ChatSessionUserDO chatSessionUserDO = ChatSessionUserDO.builder()
                    .sessionId(sessionId)
                    .userId(applyUserId)
                    .contactId(contactId)
                    .contactName(groupInfoDO.getGroupName())
                    .build();
            insertOrUpdate(chatSessionUserDO);

            // Step 6.2 添加用户通道到群聊通道
            channelContextUtil.addUser2Group(contactId, applyUserId);

            // Step 6.3 处理进群消息
            UserInfoDO userInfoDO = userInfoMapper.selectById(applyUserId);
            String sendMessage = String.format(MessageTypeEnum.ADD_GROUP.getInitMessage(), userInfoDO.getNickName());

            // Step 6.4 创建聊天会话
            ChatSessionDO chatSessionDO = ChatSessionDO.builder()
                    .sessionId(sessionId)
                    .lastMessage(sendMessage)
                    .lastReceiveTime(System.currentTimeMillis())
                    .build();
            chatSessionMapper.insertOrUpdate(chatSessionDO);

            // Step 6.5 创建消息
            ChatMessageDO chatMessageDO = ChatMessageDO.builder()
                    .sessionId(sessionId)
                    .sendUserId(applyUserId)
                    .sendUserNickName(userInfoDO.getNickName())
                    .messageType(MessageTypeEnum.ADD_GROUP.getType())
                    .messageContent(sendMessage)
                    .contactId(contactId)
                    .contactType(UserContactTypeEnum.GROUP.getType())
                    .status(MessageStatusEnum.SENT.getStatus())
                    .build();
            chatMessageMapper.insert(chatMessageDO);

            MessageSendDTO<Object> messageSendDTO = BeanUtil.copyProperties(chatMessageDO,  MessageSendDTO.class);

            // Step 6.6 查询群组成员数
            QueryWrapper<UserContactDO> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(UserContactDO::getContactId, contactId);
            Long count = userContactMapper.selectCount(queryWrapper);
            messageSendDTO.setMemberCount(count);
            messageSendDTO.setContactName(groupInfoDO.getGroupName());

            // Step 6.7 发送进群消息
            messageHandler.sendMessage(messageSendDTO);
        }
    }

    @Override
    public List<LoadContactResponse> loadContact(String userId, Integer contactType) {
        // Step 1. 聊天类型校验
        UserContactTypeEnum typeEnum = UserContactTypeEnum.getByType(contactType);
        if (null == typeEnum) {
            throw new ServiceException(ServiceErrorCodeConstants.CONTACT_TYPE_WRONG);
        }

        // Step 2. 判断是群组还是好友
        if (typeEnum.equals(UserContactTypeEnum.USER)) {
            return userContactMapper.selectUserFriends(userId);
        } else {
            return userContactMapper.selectUserGroups(userId);
        }
    }

    @Override
    public GetContactInfoResponse getContactInfo(String userId, String contactId) {
        // Step 1. 检查用户与联系人的关系
        QueryWrapper<UserContactDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(UserContactDO::getUserId, userId)
                .eq(UserContactDO::getContactId, contactId);
        UserContactDO userContactDO = userContactMapper.selectOne(queryWrapper);

        GetContactInfoResponse response = new GetContactInfoResponse();
        // ? 此前没有建立关系，默认为非好友关系
        response.setStatus(UserContactStatusEnum.NOT_FRIEND.getStatus());
        response.setStatusDesc(UserContactStatusEnum.NOT_FRIEND.getDesc());

        if (null != userContactDO) {
            response.setStatus(userContactDO.getStatus());
            response.setStatusDesc(Objects.requireNonNull(
                    UserContactStatusEnum.getByStatus(userContactDO.getStatus())).getDesc());
        }

        // Step 2. 检查其搜索的联系人类型（用户 | 群组）
        UserContactTypeEnum typeEnum = UserContactTypeEnum.getByPrefix(contactId);
        if (null == typeEnum) {
            throw new ServiceException(ServiceErrorCodeConstants.CONTACT_TYPE_WRONG);
        }
        // ? 用户
        if (typeEnum.equals(UserContactTypeEnum.USER)) {
            UserInfoDO userInfoDO = userInfoMapper.selectById(contactId);
            response.setContactId(userInfoDO.getUserId());
            response.setContactType(UserContactTypeEnum.USER.getDesc());
            response.setContactName(userInfoDO.getNickName());
            response.setGender(userInfoDO.getGender());
            response.setAreaName(userInfoDO.getAreaName());
        } else { // ? 群组
            GroupInfoDO groupInfoDO = groupInfoMapper.selectById(contactId);
            response.setContactId(groupInfoDO.getGroupId());
            response.setContactType(UserContactTypeEnum.GROUP.getDesc());
            response.setContactName(groupInfoDO.getGroupName());
        }

        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addRobotContact(String userId) {
        SystemSettingResponse systemSetting = redisComponent.getSystemSetting();
        // Step 1. 增加机器人为好友
        UserContactDO userContactDO = UserContactDO.builder()
                .userId(userId)
                .contactId(systemSetting.getRobotUid())
                .contactType(UserContactTypeEnum.USER.getType())
                .status(UserContactStatusEnum.FRIEND.getStatus())
                .build();
        userContactMapper.insert(userContactDO);

        String sessionId = StringUtil.getSessionId(new String[]{userId, systemSetting.getRobotUid()});
        // Step 2. 增加会话消息
        ChatSessionDO chatSessionDO = ChatSessionDO.builder()
                .sessionId(sessionId)
                .lastMessage(systemSetting.getRobotWelcome())
                .lastReceiveTime(System.currentTimeMillis())
                .build();
        chatSessionMapper.insert(chatSessionDO);

        // Step 3. 增加会话用户信息
        ChatSessionUserDO chatSessionUserDO = ChatSessionUserDO.builder()
                .sessionId(sessionId)
                .userId(userId)
                .contactId(systemSetting.getRobotUid())
                .contactName(systemSetting.getRobotNickName())
                .build();
        chatSessionUserMapper.insert(chatSessionUserDO);

        // Step 4. 增加聊天信息
        ChatMessageDO chatMessageDO = ChatMessageDO.builder()
                .sessionId(sessionId)
                .messageContent(systemSetting.getRobotWelcome())
                .messageType(MessageTypeEnum.CHAT.getType())
                .sendUserId(systemSetting.getRobotUid())
                .sendUserNickName(systemSetting.getRobotNickName())
                .contactId(userId)
                .contactType(UserContactTypeEnum.USER.getType())
                .status(MessageStatusEnum.SENT.getStatus())
                .build();
        chatMessageMapper.insert(chatMessageDO);
    }

    private Boolean isGroupMaxMembers(String contactId) {
        QueryWrapper<UserContactDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(UserContactDO::getContactId, contactId)
                .eq(UserContactDO::getStatus, UserContactStatusEnum.FRIEND.getStatus());
        Long count = userContactMapper.selectCount(queryWrapper);
        return count >= redisComponent.getSystemSetting()
                                        .getMaxGroupMemberCount();
    }

    private void insertOrUpdate(List<UserContactDO> userContactDOList) {
        for (UserContactDO userContactDO: userContactDOList) {
            insertOrUpdate(userContactDO);
        }
    }

    private void insertOrUpdate(UserContactDO userContactDO) {
        // Step 1. 检查是否是更新还是插入
        QueryWrapper<UserContactDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(UserContactDO::getUserId, userContactDO.getUserId())
                .eq(UserContactDO::getContactId, userContactDO.getContactId());
        UserContactDO userContact = userContactMapper.selectOne(queryWrapper);
        if (null == userContact) { // ? 插入
            userContactMapper.insert(userContactDO);
        } else { // ? 更新
            userContactMapper.update(userContactDO, queryWrapper);
        }
    }

    private void insertOrUpdate(List<ChatSessionUserDO> chatSessionUserDOList, Integer flag) {
        for (ChatSessionUserDO chatSessionUserDO: chatSessionUserDOList) {
            insertOrUpdate(chatSessionUserDO);
        }
    }

    private void insertOrUpdate(ChatSessionUserDO chatSessionUserDO) {
        // Step 1. 检查是否是更新还是插入
        QueryWrapper<ChatSessionUserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(ChatSessionUserDO::getUserId, chatSessionUserDO.getUserId())
                .eq(ChatSessionUserDO::getContactId, chatSessionUserDO.getContactId());
        ChatSessionUserDO chatSessionUser = chatSessionUserMapper.selectOne(queryWrapper);
        if (null == chatSessionUser) { // ? 插入
            chatSessionUserMapper.insert(chatSessionUserDO);
        } else { // ? 更新
            chatSessionUserMapper.update(chatSessionUserDO, queryWrapper);
        }
    }

}
